﻿using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Cmp;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Zocono.Infrastructure.Common;
using Zocono.WCS.Comm;
using Zocono.WCS.Domain.DomainRepository;
using Zocono.WCS.Domain.EntityInfo;
using Zocono.WCS.Domain.FSJDomain;
using Zocono.WCS.Domain.JobExcutorDomain;
using Zocono.WCS.Domain.LogDomain;
using Zocono.WCS.Domain.PlcBytesObject;
using Zocono.WCS.Domain.PlcConnectPoolDomain;
using Zocono.WCS.Domain.ProcessModuleDomain;
using Zocono.WCS.Infrastructure.ApllicationDto.Enums;
using Zocono.WCS.Infrastructure.ApllicationDto.FxModel;
using Zocono.WCS.Infrastructure.ApllicationDto.WCSTaskDto;
using Zocono.WCS.Infrastructure.PlcCommon;
using Zocono.WCS.WMSApiDomain;
using Zocono.WCS.WMSApiDomain.WebApi;

namespace Zocono.WCS.Domain.EquipmentProcessDomain.PlanarGeneralMessage
{
    /// <summary>
    /// 响应PLC 2，WCS 0 动作
    /// </summary>
    public class FSJWorker_2Service : IPlanarGeneralPlcActionProcessService
    {
        private readonly ILogUtil _LogUtil;
        private readonly IPlcConnectionPool _PlcConnectionPool;
        private readonly IWorkTaskInfoRepository _WorkTaskInfoRepository;
        private readonly IPlcWriteDbInfoRepository _PlcWriteDbInfoRepository;
        private readonly IPlcConnectionInfoRepository _PlcConnectionInfoRepository;
        private readonly IPlcPointInfoRepositpry _IPlcPointInfoRepositpry;
        private readonly IPlcConnectionStateInfoRepository _IPlcConnectionStateInfoRepository;
        private readonly IRunLogInfoService _IRunLogInfoService;
        private readonly IFSJMesService _IFSJMesService;
        private readonly IPlcReadDbInfoRepository _PlcReadDbInfoRepository;

        public FSJWorker_2Service(ILogUtil logUtil
            , IPlcConnectionPool plcConnectionPool
            , IWorkTaskInfoRepository workTaskInfoRepository
            , IPlcWriteDbInfoRepository plcWriteDbInfoRepository
            , IPlcConnectionInfoRepository plcConnectionInfoRepository,
            IPlcPointInfoRepositpry plcPointInfoRepositpry
             , IPlcConnectionStateInfoRepository plcConnectionStateInfoRepository
            , IRunLogInfoService runLogInfoService,
            IFSJMesService iFSJMesService,
             IPlcReadDbInfoRepository plcReadDbInfoRepository
            )
        {
            _LogUtil = logUtil;
            _PlcConnectionPool = plcConnectionPool;
            _WorkTaskInfoRepository = workTaskInfoRepository;
            _PlcWriteDbInfoRepository = plcWriteDbInfoRepository;
            _PlcConnectionInfoRepository = plcConnectionInfoRepository;
            _IPlcPointInfoRepositpry = plcPointInfoRepositpry;
            _IPlcConnectionStateInfoRepository = plcConnectionStateInfoRepository;
            _IRunLogInfoService = runLogInfoService;
            _IFSJMesService = iFSJMesService;
            _PlcReadDbInfoRepository = plcReadDbInfoRepository;
        }

        public async Task ProcessActionMessageAsync(BytesObjectBase plcActionMessage, BytesObjectBase wcsActionMessage, EquipmentDbObject planarEquipmentDbObject/*, BytesObjectBase plcStateMassge*/)
        {
            /*
            * 业务需求：
            * 1.托盘进入分选机，分选机获取托盘的信息 调用wms接口 public async Task<ReturnContainer> GetContainerMsg(AutoSelectParaIn autoSelectParaIn)，获得电芯信息
            * 2.根据电芯条码，向MES获取电芯的详细信息（电芯电压，容量 等信息），托盘一到分选机托盘解绑
            * 3、根据电芯详情信息，和档位配置参数，进行分档，并把电芯分档信息写入plc
            * 4、机器人进行分选，托盘解绑，组盘绑定
            * 5、1）留在分选托盘的电芯入库；2）档位上的托盘满盘则留到下一个节点（NG档位走排出，复测档位走下个流程，正常档位流入库）
            * 6、组盘电芯上报到Mes

           /*
            * 处理逻辑
            * 1. 验证plc是否在线
            * 2. 验证当前设备是否报警
            * 3. 验证wcs任务，验证wcs当前子任务(待执行、执行中)，当前子任务已经是SC完成后更新了
            * 4. 组织plc报文，写入plc
            */





            //await _AisleRequestService.ProcessActionMessageAsync(plcActionMessage,  wcsActionMessage,  planarEquipmentDbObject);

            //var wmsTaskInfoDto = await WCSMessageWithWMSApi.WCSCreatUploadWarehouseWMSTaskAsync(ContainerBarcode, EquipmentCode);

            //var a = await WCSMessageWithWMSApi.WCSUpdateWMStaskStateAndProcessTaskStateAsync(wmsTaskInfoDto.Result.TaskCode, 1, 1);



            //var objectType = typeof(PlanarGeneralWriteWcsAction).Name;
            //var writeConfig = await _PlcWriteDbInfoRepository.GetFirstAsync(it => it.EquipmentCode == plcMessage.EquipmentCode && it.ObjectType == objectType);

            //PlanarGeneralWriteWcsAction writeAlrmBo = new PlanarGeneralWriteWcsAction(
            //    writeConfig.PlcConnectionId,
            //    writeConfig.ID,
            //    writeConfig.DbCode,
            //    writeConfig.DbStart,
            //    objectType,
            //    plcMessage.EquipmentCode.ToInt32(),
            //    2,
            //    Convert.ToInt32(wmsTaskInfoDto.Result.EndPosition),
            //    Convert.ToInt32(wmsTaskInfoDto.Result.TaskCode),
            //    ContainerBarcode,
            //    1,
            //    0);

            //RunLogInfo runLogInfo = new RunLogInfo();
            //runLogInfo.ContainerBarcode = plcMessage.PalletBarcode;
            //runLogInfo.EquipmentCode = plcMessage.EquipmentCode;
            //runLogInfo.RunType = "到达分选台";

            //runLogInfo.RunLog = "分选任务开始";

            //var plcConn = _PlcConnectionPool.S7GetWritePlcConnection(plcMessage.PlcConnectionID);


            //if (plcConn == null)
            //{
            //    runLogInfo.RunLog = $"获取连接({plcMessage.PlcConnectionID})失败";
            //    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
            //    return;
            //}

            //var plcIPStates = await _IPlcConnectionStateInfoRepository.GetFirstAsync(l => l.PlcConnectionID == plcMessage.PlcConnectionID && l.Connected == true);
            //if (plcIPStates == null)
            //{
            //    runLogInfo.RunLog = $"{plcConn.IP}plc已离线";
            //    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
            //    return;
            //}
            //if (plcMessage.AlrmCode != 0)
            //{
            //    runLogInfo.RunLog = $"报警,报警代码：{plcMessage.AlrmCode}";
            //    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
            //    return;
            //}

            //var res = await plcConn.WriteDbAsync(writeAlrmBo.DbCode, writeAlrmBo.DbStart, writeAlrmBo.Deserialize());



            //// 记录运行日志
            //runLogInfo.RunLog = $"PLC写入报文内容： {JsonConvert.SerializeObject(writeAlrmBo)}";
            //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);





            //runLogInfo.RunLog = $"到达DO处理成功";
            //await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);





        }

        private async Task<bool> doPutMesResultDate(BytesObjectBase plcActionMessage, BytesObjectBase wcsActionMessage, EquipmentDbObject planarEquipmentDbObject)
        {
            //获取PLC写DB配置
            //PlcWriteDbInfo writeDbInfo = await _PlcWriteDbInfoRepository.GetFirstAsync(
            //   it => it.EquipmentCode == readPlc.EquipmentCode);
            //_IFSJMesService.PutMesResultDatasAsync();

            var plcMessage = plcActionMessage as PlanarGeneralPlcActionBO;//Plc的动作报文
            var wcsMessage = wcsActionMessage as PlanarGeneralWcsActionBO;//Wcs的动作报文
            plcMessage.PalletBarcode = plcMessage.PalletBarcode.Trim();


            var ContainerBarcode = plcMessage.PalletBarcode.Trim();
            var EquipmentCode = plcMessage.EquipmentCode.Trim();

            //TODO 提交分选结果数据上传Mes，后申请目标位置服务
            //获取PLC条码DB配置，PLC名称包含设备码
            var barcodeDb = await _PlcReadDbInfoRepository
                .GetFirstAsync(it =>
                it.DbCode == 1000 &&
                it.PlcName.Contains(EquipmentCode)
                );

            //读取条码
            var plcConn = _PlcConnectionPool.S7GetWritePlcConnection(plcMessage.PlcConnectionID);
            byte[] barcodeBytes = await plcConn.ReadDbAsync(barcodeDb.DbCode, barcodeDb.DbStart, barcodeDb.DbLength);
            if (barcodeBytes != null)
            {
                //读取成功
                PlanarGeneralPlcActionBOFx readPlcBarcode = new PlanarGeneralPlcActionBOFx();
                readPlcBarcode.Serialize(
                    barcodeDb.PlcConnectionID,
                    barcodeDb.ID,
                    barcodeDb.DbStart,
                    barcodeBytes.Count(),
                    0,
                    barcodeDb.DbLength,
                    barcodeDb.ProcessModuleName,
                    barcodeDb.EquipmentCode,
                    barcodeBytes
                    );
                _LogUtil.Debug($"读取电芯数据：{EquipmentCode}," + JsonHelper.SerializeObject(readPlcBarcode));

                

                PutMesResultDatasInput input = new PutMesResultDatasInput();

                List<PutInData> putInDatas = new List<PutInData>();

                foreach (var item in readPlcBarcode.Infos)
                {
                    PutInData putInData = new PutInData();
                    putInData.EquipCode = EquipmentCode;
                    putInData.CellCode = item.code;
                    putInData.Result = "";
                    putInData.StartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    putInData.NGReason = "";
                    putInData.TrayCode = ContainerBarcode;
                    putInData.GradeName = item.res.ToString();
                    putInData.Position = item.location.ToString();
                    putInData.ResponseTime = DateTime.Now;
                    putInData.CollectTime = DateTime.Now;
                    putInData.QRCodeLevel = "";
                    putInData.matchingResult = "";
                    putInDatas.Add(putInData);
                }

                //PutMesResultDatasInput input = new PutMesResultDatasInput();
                input.ProtocolNO = "";
                input.MsgNO = 1;
                input.NeedReply = 1;
                input.CmdID = "";
                input.EID = "";
                input.Data = putInDatas;

                var isTrue = await _IFSJMesService.PutMesResultDatasAsync(input);

                if (isTrue.Data.FirstOrDefault().Msg == "")
                {

                    // 申请目标位置服务
                    var instance = ServiceProviderInstance.GetServiceByClassNmae<IPlanarGeneralPlcActionProcessService>(nameof(AisleRequestService));
                    await instance.ProcessActionMessageAsync(plcActionMessage, wcsActionMessage, planarEquipmentDbObject);

                }
            }

            return true;
        }
    }
}
